package com.smart.manager.finance.repository;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.smart.common.entities.core.BaseSearch;
import com.smart.common.entities.core.Page;
import com.smart.common.entities.file.UploadBody;
import com.smart.common.entities.file.UploadResult;
import com.smart.common.excle.domain.ExcleExportRs;
import com.smart.common.excle.domain.ExcleFiledEntity;
import com.smart.common.excle.utils.SmartExcleUtil;
import com.smart.manager.finance.entities.bodys.ROrderCoin;
import com.smart.manager.finance.entities.enums.PayState;
import com.smart.manager.finance.entities.export.FinanceOrderCoinExcel;
import com.smart.manager.finance.entities.models.FinanceOrderCoin;
import com.smart.manager.finance.entities.models.query.QFinanceOrderCoin;
import com.smart.service.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 支付中心-订单管理
 *
 * @author Administrator
 */

@Log4j2
@Service
@RequiredArgsConstructor
public class OrderCoinRepository {

    private final FileService fileService;


    public Page<FinanceOrderCoin> pageList(ROrderCoin.SearchBody search) {
        QFinanceOrderCoin query = new QFinanceOrderCoin();
        Opt.ofBlankAble(search.getPayPlatform()).ifPresent(x -> query.payPlatform.eq(x));
        Opt.ofBlankAble(search.getAppId()).ifPresent(x -> query.appId.contains(x));
        Opt.ofBlankAble(search.getAppType()).ifPresent(x -> query.appType.eq(x));
        Opt.ofBlankAble(search.getNickName()).ifPresent(x -> query.member.nickName.contains(x));
        Opt.ofBlankAble(search.getPhoneNumber()).ifPresent(x -> query.member.phoneNumber.contains(x));
        Opt.ofBlankAble(search.getPayState()).ifPresent(x -> query.payState.eq(x));
        Opt.ofBlankAble(search.getOpenIdKind()).ifPresent(x -> query.openIdKind.eq(x));
        Opt.ofBlankAble(search.getOrderId()).ifPresent(x -> query.orderId.contains(x));
        Opt.ofBlankAble(search.getTransactionId()).ifPresent(x -> query.transactionId.contains(x));
        Opt.ofEmptyAble(search.getActionTime()).ifPresent(x -> {
            query.actionTime
                    .between(
                            LocalDateTime.parse(x.get(0)+" 00:00:00", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)),
                            LocalDateTime.parse(x.get(1)+" 23:59:59", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))
                    );
        });

        Opt.ofEmptyAble(search.getFinishTime()).ifPresent(x -> {
            query.finishTime
                    .between(
                            LocalDateTime.parse(x.get(0)+" 00:00:00", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)),
                            LocalDateTime.parse(x.get(1)+" 23:59:59", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))
                    );
        });
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows()).order().id.desc();
        return new Page<FinanceOrderCoin>().load(query.findPagedList());
    }

    /**
     * 表格导出
     * @param search 查询条件
     * @return
     */
    public ExcleExportRs export(ROrderCoin.SearchBody search) {
        QFinanceOrderCoin query = new QFinanceOrderCoin();
        Opt.ofBlankAble(search.getPayPlatform()).ifPresent(x -> query.payPlatform.eq(x));
        Opt.ofBlankAble(search.getAppId()).ifPresent(x -> query.appId.contains(x));
        Opt.ofBlankAble(search.getAppType()).ifPresent(x -> query.appType.eq(x));
        Opt.ofBlankAble(search.getNickName()).ifPresent(x -> query.member.nickName.contains(x));
        Opt.ofBlankAble(search.getPhoneNumber()).ifPresent(x -> query.member.phoneNumber.contains(x));
        Opt.ofBlankAble(search.getPayState()).ifPresent(x -> query.payState.eq(x));
        Opt.ofBlankAble(search.getOpenIdKind()).ifPresent(x -> query.openIdKind.eq(x));
        Opt.ofBlankAble(search.getOrderId()).ifPresent(x -> query.orderId.contains(x));
        Opt.ofBlankAble(search.getTransactionId()).ifPresent(x -> query.transactionId.contains(x));
        Opt.ofEmptyAble(search.getActionTime()).ifPresent(x -> {
            query.actionTime
                    .between(
                            LocalDateTime.parse(x.get(0)+" 00:00:00", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)),
                            LocalDateTime.parse(x.get(1)+" 23:59:59", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))
                    );
        });

        Opt.ofEmptyAble(search.getFinishTime()).ifPresent(x -> {
            query.finishTime
                    .between(
                            LocalDateTime.parse(x.get(0)+" 00:00:00", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)),
                            LocalDateTime.parse(x.get(1)+" 23:59:59", DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))
                    );
        });
        List<FinanceOrderCoin> orderCoinList = query.findList();
        //格式化数据
        List<FinanceOrderCoinExcel> coinExcels = orderCoinList.stream().map(x -> {
            FinanceOrderCoinExcel excel = BeanUtil.copyProperties(x, FinanceOrderCoinExcel.class);
            Opt.ofNullable(x.getMember()).ifPresent(c -> excel.setMember(c.getNickName()));
            Opt.ofNullable(x.getMember()).ifPresent(c -> excel.setMemberP(c.getPhoneNumber()));
            Opt.ofNullable(x.getPayPlatform()).ifPresent(c -> excel.setPayPlatform(c.getLabel()));
            Opt.ofNullable(x.getPayState()).ifPresent(c -> excel.setPayState(c.getLabel()));
            Opt.ofNullable(x.getAppType()).ifPresent(c -> excel.setAppType(c.getLabel()));
            Opt.ofNullable(x.getOpenIdKind()).ifPresent(c -> excel.setOpenIdKind(c.getLabel()));
            return excel;
        }).collect(Collectors.toList());
        ByteArrayOutputStream exportStream = SmartExcleUtil.getExportStream(coinExcels, null);
        UploadBody.ByteFile byteFile = new UploadBody.ByteFile();
        byteFile.setData(exportStream.toByteArray()).setContentType(".xlsx");
        UploadResult uploadResult = fileService.uploadFileByByte(byteFile, null, null);
        return new ExcleExportRs().setCount(coinExcels.size()).setDownUrl(uploadResult.getUrl());
    }


    /**
     * 封装导出数据
     *
     * @param objList
     * @param tClass
     */
    private void tableExport(List<?> objList, Class<?> tClass) {
        //输出流
        ExcelWriter writer = ExcelUtil.getBigWriter();

        //输出文件
//        ExcelWriter writer = ExcelUtil.getBigWriter("C:/Users/leo/Desktop/H3C/bbb/writeBeanTest.xlsx");
        List<ExcleFiledEntity> fieldList = SmartExcleUtil.getFieldList(tClass);
        //字段先后排序
        Collections.sort(fieldList, Comparator.comparing(ExcleFiledEntity::getFieldSort));
        fieldList.forEach(x -> {
            writer.addHeaderAlias(x.getFieldCode(), x.getFieldName());
        });
        writer.setOnlyAlias(true);
        writer.write(objList, true);
        //设置宽度
        List<String> list = fieldList.stream().map(ExcleFiledEntity::getFieldCode).collect(Collectors.toList());
        fieldList.forEach(x -> {
            //根据每行设置宽度
            int index = list.indexOf(x.getFieldCode());
            writer.setColumnWidth(index, x.getWidth());
        });
        //输出流
//        writer.flush()
        writer.close();
        //TODO: 等待实现 , 这里上传到OSS 返回String 的URL访问地址
    }


    /**
     * 根据订单编号查询订单信息是否存在
     *
     * @param orderId 订单编号
     * @return {@code FinanceOrderCoin}
     */
    public FinanceOrderCoin getOneByOrderId(String orderId) {
        FinanceOrderCoin orderCoin = new QFinanceOrderCoin().orderId.eq(orderId).setMaxRows(1).findOne();
        Assert.notNull(orderCoin, "订单信息不存在");
        return orderCoin;
    }


    /**
     * @param memberId member数据主键
     * @param search   分页条件
     * @return {@link Page}<{@link FinanceOrderCoin}>
     */
    public Page<FinanceOrderCoin> myPageList(Long memberId, BaseSearch search) {
        QFinanceOrderCoin query = new QFinanceOrderCoin();
        query.member.id.eq(memberId).payState.eq(PayState.PAID).setFirstRow(search.firstRow()).setMaxRows(search.maxRows()).order().id.desc();
        return new Page<FinanceOrderCoin>().load(query.findPagedList());
    }


    /**
     * 获取订单详情
     *
     * @param memberId member数据主键
     * @param orderId  order数据主键
     * @return {@link FinanceOrderCoin}
     */
    public FinanceOrderCoin getPayDetail(Long memberId, String orderId) {
        QFinanceOrderCoin query = new QFinanceOrderCoin();
        FinanceOrderCoin record = query.orderId.eq(orderId).member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(record, "订单信息不存在");
        return record;

    }
}
